﻿[assembly: System.Web.UI.TagPrefix("GSC.WebControls", "GSC")]
namespace GSC.WebControls
{
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Web.UI;
    using System.Reflection;
    using System.IO;
    using System.Web.Script.Serialization;
    using System.Web;
    using System.Web.UI.WebControls;
    using System.Globalization;
    using System.ComponentModel;
	[PersistChildren(false)]
	[ParseChildren(true)]
	[NonVisualControl]
    [Designer(typeof(AjaxFileUploadHelperDesigner))]
	public class AjaxFileUploadHelper : WebControl, INamingContainer
	{
		// ScriptManager members;
		private static FieldInfo isInAsyncPostBackFieldInfo;
		private static PropertyInfo pageRequestManagerPropertyInfo;

		// PageRequestManager members;
		private static MethodInfo onPageErrorMethodInfo;
		private static MethodInfo renderPageCallbackMethodInfo;


		static AjaxFileUploadHelper()
		{
			Type scriptManagerType = typeof(ScriptManager);
			isInAsyncPostBackFieldInfo = scriptManagerType.GetField(
				"_isInAsyncPostBack",
				BindingFlags.Instance | BindingFlags.NonPublic);
			pageRequestManagerPropertyInfo = scriptManagerType.GetProperty(
				"PageRequestManager",
				BindingFlags.Instance | BindingFlags.NonPublic);

			Assembly assembly = scriptManagerType.Assembly;
			Type pageRequestManagerType = assembly.GetType("System.Web.UI.PageRequestManager");
			onPageErrorMethodInfo = pageRequestManagerType.GetMethod(
				"OnPageError", BindingFlags.Instance | BindingFlags.NonPublic);
			renderPageCallbackMethodInfo = pageRequestManagerType.GetMethod(
				"RenderPageCallback", BindingFlags.Instance | BindingFlags.NonPublic);
		}



		public static AjaxFileUploadHelper GetCurrent(Page page)
		{
			return page.Items[typeof(AjaxFileUploadHelper)] as AjaxFileUploadHelper;
		}

		private bool isInAjaxUploading = false;

		private bool _SupportAjaxUpload = true;

		public bool SupportAjaxUpload
		{
			get { return _SupportAjaxUpload; }
			set { _SupportAjaxUpload = value; }
		}
        protected override HtmlTextWriterTag TagKey
        {
            get
            {
                return HtmlTextWriterTag.Div;
            }
        }
        protected override void AddAttributesToRender(HtmlTextWriter writer)
        {
            writer.AddStyleAttribute(HtmlTextWriterStyle.Display, "none");
            writer.AddStyleAttribute(HtmlTextWriterStyle.FontSize, "0px");
            writer.AddStyleAttribute(HtmlTextWriterStyle.Overflow, "hidden");
            base.AddAttributesToRender(writer);
        }
        protected override void CreateChildControls()
        {
            if (_SupportAjaxUpload)
            {
                this.Controls.Add(new FileUpload());
            }
            base.CreateChildControls();
        }
		protected override void OnInit(EventArgs e)
		{
			base.OnInit(e);
            if (!this.DesignMode)
            {
                if (this.Page.Items.Contains(typeof(AjaxFileUploadHelper)))
                {
                    throw new InvalidOperationException("页面没有上传扩展错误！");
                }
                this.Page.Items[typeof(AjaxFileUploadHelper)] = this;
                this.EnsureIsInAjaxFileUploading();
            }
		}

		protected override void OnPreRender(EventArgs e)
		{
			base.OnPreRender(e);

			if (this.isInAjaxUploading)
			{
				this.Page.SetRenderMethodDelegate(new RenderMethod(this.RenderPageCallback));
			}

			if (this.Page.IsPostBack || !this.SupportAjaxUpload) return;

			if (!ScriptManager.GetCurrent(this.Page).IsInAsyncPostBack)
			{
                ScriptManager.GetCurrent(this.Page).Scripts.Add(new ScriptReference("GSC.WebControls.AjaxFileUploadHelper.js", this.GetType().Assembly.FullName));
			}
		}

		private void RenderPageCallback(HtmlTextWriter writer, Control pageControl)
		{
			AjaxFileUploadUtility.WriteScriptBlock(this.Page.Response, true);

			StringBuilder sb = new StringBuilder();
			HtmlTextWriter innerWriter = new HtmlTextWriter(new StringWriter(sb));
			renderPageCallbackMethodInfo.Invoke(this.PageRequestManager, new object[] { innerWriter, pageControl });

			writer.Write(sb.Replace("*/", "*//*").ToString());

			AjaxFileUploadUtility.WriteScriptBlock(this.Page.Response, false);
		}

		private void EnsureIsInAjaxFileUploading()
		{
			this.isInAjaxUploading = AjaxFileUploadUtility.IsInIFrameAsyncPostBack(this.Page.Request.Params);

			if (this.isInAjaxUploading)
			{
				isInAsyncPostBackFieldInfo.SetValue(
					ScriptManager.GetCurrent(this.Page),
					true);

				this.Page.Error += new EventHandler(Page_Error);
			}
		}

		private void Page_Error(object sender, EventArgs e)
		{
			AjaxFileUploadUtility.WriteScriptBlock(this.Page.Response, true);

			onPageErrorMethodInfo.Invoke(this.PageRequestManager, new object[] { sender, e });

			AjaxFileUploadUtility.WriteScriptBlock(this.Page.Response, false);
		}

		private object _PageRequestManager;

		private object PageRequestManager
		{
			get
			{
				if (this._PageRequestManager == null)
				{
					this._PageRequestManager = pageRequestManagerPropertyInfo.GetValue(
						ScriptManager.GetCurrent(this.Page), null);
				}

				return this._PageRequestManager;
			}
		}
	}
}
